<template>
  <a-row :class="['p-4', `${prefixCls}--box`]" type="flex" :gutter="10">
    <a-col class="left-calendar" style="width: 250px">
      <div class="calendar-search">
        <Icon icon="ant-design:search-outlined" class="icon-search" style="font-size: 16px; display: inline-flex" />
        <a-input
          v-model:value="search_input"
          placeholder='在"分类日程"条件中搜索'
          class="calendar-search-box"
          @pressEnter="handleSearch"
          allowClear
        />
      </div>
      <div class="calendar-type" style="display: flex; height: 100%">
        <span class="font-color">分类日程</span>
      </div>
      <div class="calendar-type-List">
        <ul>
          <!-- <li v-for="item in planOptions" :key="item.value">
            <a-checkbox :value="item.value" v-model:checked="item.checked" :indeterminate="planState.indeterminate" @change="handleCheckedChange">{{
              item.label
            }}</a-checkbox>
          </li> -->
          <li
            ><a-checkbox v-model:checked="planState.checkedDailyRecords" :indeterminate="planState.indeterminate" @change="handleCheckedChange"
              >日常记录</a-checkbox
            ></li
          >
          <li
            ><a-checkbox v-model:checked="planState.checkedWorkThisWeek" :indeterminate="planState.indeterminate" @change="handleCheckedChange"
              >本周工作</a-checkbox
            ></li
          >
          <li
            ><a-checkbox v-model:checked="planState.checkedNextWeeksPlan" :indeterminate="planState.indeterminate" @change="handleCheckedChange"
              >下周计划</a-checkbox
            ></li
          >
          <li>
            <a-checkbox v-model:checked="planState.checkedParticipating" :indeterminate="planState.indeterminate" @change="handleCheckedChange" />
            <a-select
              v-model:value="planState.selectedParticipating"
              style="width: 110px"
              :options="planParticipatingOptions"
              @change="handleSelectedChange"
              class="task-select"
            />
          </li>
        </ul>
      </div>
    </a-col>
    <a-col style="width: calc(100% - 250px); float: left">
      <div class="right-left-header" style="display: flex; margin-bottom: 2px">
        <!-- 日历头部左侧-今天 -->
        <a-button class="today" size="medium" @click="handleToday">今天</a-button>
        <!-- 日历头部左侧-日期 -->
        <div style="float: left; margin-left: 0.75em">
          <a-button class="prev-next" preIcon="ant-design:left-outlined" @click="handlePrev" />
          <a-button class="prev-next" preIcon="ant-design:right-outlined" @click="handleNext" />
          <h2
            >{{ calendar_view_title }}<span style="margin-left: 10px">{{ calendar_view_sub_title }}</span></h2
          >
        </div>
        <!-- 日历头部中间 -->
        <div class="right-center-header">
          <div class="fc-button-group">
            <a-button @click="handleMonth" :class="buttonGroup == 'month' ? 'common-button  border-color' : 'common-button'">月</a-button>
            <a-button @click="handleWeek" :class="buttonGroup == 'week' ? 'common-button  border-color' : 'common-button'">周</a-button>
            <a-button @click="handleDay" :class="buttonGroup == 'day' ? 'common-button  border-color' : 'common-button'">日</a-button>
            <a-button @click="handleList" :class="buttonGroup == 'list' ? 'common-button  border-color' : 'common-button'">列表</a-button>
          </div>
        </div>
        <!-- 日历头部右侧 -->
        <div class="right-right-header">
          <a-button class="right-button" preIcon="ant-design:plus-outlined" @click="handleCreateClick">新日程</a-button>
        </div>
      </div>

      <div class="mouth-full-calendar" style="margin-top: 48px; padding: 0px">
        <div class="ant-card ant-card-bordered full-calendar" :border="false">
          <div class="ant-card-body">
            <!-- 日历本体 -->
            <a-row>
              <a-col :md="24" :xs="24">
                <div style="margin-top: 0px">
                  <FullCalendar class="calendar" ref="fullCalendar" :options="calendarOptions">
                    <template #eventContent="arg">
                      <a-popover placement="leftTop" trigger="hover" :open-delay="100">
                        <div style="overflow: hidden">
                          <div
                            v-if="arg.event.extendedProps.eventShowType == 3 && arg.view.type != 'listMonth'"
                            class="event-dot"
                            :style="{ 'border-color': arg.event.extendedProps.dotColor, display: 'inline-block' }"
                          ></div>
                          <span
                            v-if="
                              (arg.event.extendedProps.eventShowType == 2 || arg.event.extendedProps.eventShowType == 3) &&
                              arg.view.type != 'listMonth'
                            "
                            style="display: inline-block; margin-right: 5px"
                            >{{ arg.timeText }}</span
                          >
                          <span style="display: inline-block">{{ arg.event.title }}</span>
                        </div>
                        <template #title>
                          <a-row class="popover_title">
                            <a-col
                              :span="12"
                              :style="{
                                color: '5px solid ' + arg.event.extendedProps.dotColor,
                              }"
                            >
                              <span
                                style="padding-right: 2px"
                                :style="{
                                  'border-left': '5px solid ' + arg.event.extendedProps.dotColor,
                                }"
                              >
                              </span
                              >{{
                                arg.event.extendedProps.status == 0
                                  ? '未开始'
                                  : arg.event.extendedProps.status == 1
                                  ? '进行中'
                                  : arg.event.extendedProps.status == 2
                                  ? '已完成'
                                  : '已延时'
                              }}
                            </a-col>
                            <a-col :span="12" style="display: flex; flex-direction: row-reverse; font-size: 14; color: #000">
                              {{ arg.event.allDay == true ? '全天' : formatTimer(arg.event.start) }}
                            </a-col>
                          </a-row>
                        </template>
                        <template #content>
                          <div style="max-width: 600px">
                            <a-row v-if="arg.event.extendedProps.imgs.length != 0">
                              <a-col :span="24" style="text-align: left">
                                <ImagePreview :imageList="arg.event.extendedProps.imgs" />
                              </a-col>
                            </a-row>
                            <a-row class="popover_content">
                              <a-col :span="24" style="max-height: 150px; overflow: auto">
                                <span class="click"
                                  ><strong>{{ arg.event.title }}</strong></span
                                >
                                <br />
                                <div v-html="arg.event.extendedProps.remark"></div>
                              </a-col>
                            </a-row>
                            <a-row class="popover_content">
                              <a-col v-if="arg.event.extendedProps.files.length != 0" :span="24">
                                <template v-for="(item, index) in arg.event.extendedProps.files" :key="index">
                                  <a type="link" @click="fileDownload(item.url)">
                                    {{ item.name }}
                                  </a>
                                  <br />
                                </template>
                              </a-col>
                            </a-row>
                            <a-row style="margin-top: 5px" v-if="arg.event.extendedProps.responsible">
                              <a-col style="width: 30px">
                                <a-button
                                  size="small"
                                  preIcon="ant-design:eye-outlined"
                                  type="primary"
                                  @click="handleEditClick(arg)"
                                  shape="circle"
                                />
                              </a-col>
                              <a-col style="width: 30px">
                                <a-button
                                  size="small"
                                  preIcon="ant-design:edit-outlined"
                                  type="primary"
                                  @click="handleEditClick(arg)"
                                  shape="circle"
                                />
                              </a-col>
                              <a-col style="width: 30px">
                                <a-button
                                  size="small"
                                  preIcon="ant-design:file-done-outlined"
                                  type="success"
                                  @click="handleCheckedClick(arg)"
                                  shape="circle"
                                />
                              </a-col>
                              <a-col style="width: 30px">
                                <a-button
                                  size="small"
                                  preIcon="ant-design:delete-outlined"
                                  type="danger"
                                  @click="handleRemoveClick(arg)"
                                  shape="circle"
                                />
                              </a-col>
                            </a-row>
                          </div>
                        </template>
                      </a-popover>
                    </template>
                  </FullCalendar>
                </div>
              </a-col>
            </a-row>
          </div>
        </div>
      </div>
    </a-col>
  </a-row>
  <CalendarModal @register="registerModal" @success="reload" />
</template>

<script>
  import { ref, defineComponent, onMounted, reactive } from 'vue';
  import { ScrollContainer } from '/@/components/Container/index';
  import { Calendar } from '@fullcalendar/core';
  import { useModal } from '/@/components/Modal';
  import FullCalendar from '@fullcalendar/vue3';
  import dayGridPlugin from '@fullcalendar/daygrid';
  import timeGridPlugin from '@fullcalendar/timegrid';
  import listPlugin from '@fullcalendar/list';
  import interactionPlugin from '@fullcalendar/interaction';
  import moment from 'moment-timezone';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { useRoute } from 'vue-router';
  import { calendar } from './calendar';
  import { ImagePreview } from '/@/components/Preview/index';
  import { getTaskList, deleteTask, checkedTask } from './calendar.api';
  import CalendarModal from './CalendarModal.vue';
  import { useDesign } from '/@/hooks/web/useDesign';
  import { useUserStore } from '/@/store/modules/user';

  export default defineComponent({
    name: 'SystemCalendar',
    components: { FullCalendar, ImagePreview, CalendarModal },
    setup() {
      const { prefixCls } = useDesign('calendar');
      const route = useRoute();
      const userStore = useUserStore();
      const fullCalendar = ref(null);
      // 当前登录人ID
      const userId = userStore.getUserInfo.id;
      // 搜索框输入的文本
      const search_input = ref('');
      // 日历标题-年月
      const calendar_view_title = ref(null);
      // 日历标题-星期、周
      const calendar_view_sub_title = ref(null);
      // 日历选中按钮
      const buttonGroup = ref('month');
      // 图片是否显示
      const img_dialogVisible = ref(false);
      // 预览图片地址
      const dialogImageUrl = ref('');
      // 附件地址存放
      const filelist = ref([]);
      // 筛选条件
      const planOptions = ref([
        { label: '日常记录', value: '0' },
        { label: '本周工作', value: '1' },
        { label: '下周计划', value: '2' },
      ]);
      const planParticipatingOptions = ref([
        {
          value: '0',
          label: '参与的任务',
        },
        {
          value: '1',
          label: '负责的任务',
        },
      ]);
      const planState = reactive({
        indeterminate: false,
        checkedDailyRecords: true,
        checkedWorkThisWeek: true,
        checkedNextWeeksPlan: true,
        checkedParticipating: true,
        selectedParticipating: '0',
      });

      const { createMessage: $message } = useMessage();
      const [registerModal, { openModal }] = useModal();

      // FullCalendar中文文档 https://blog.csdn.net/qq_39863107/article/details/105387879
      const calendarOptions = reactive({
        visibleRange: { start: '2000-01-01', end: '2100-12-31' }, // 可视化区间，必须设置，否则查询列表不会显示事件
        // validRange: { start: "2021-09-01", end: "2021-09-01" }, // 可展示区间
        // 引入的插件，比如fullcalendar/daygrid，fullcalendar/timegrid引入后才可显示月，周，日
        plugins: [dayGridPlugin, interactionPlugin, timeGridPlugin, listPlugin],
        initialView: 'dayGridMonth', // 默认为那个视图（月：dayGridMonth，周：timeGridWeek，日：timeGridDay）
        firstDay: 1, // 设置一周中显示的第一天是哪天，周日是0，周一是1，类推
        locale: 'zh-cn', // 切换语言，当前为中文
        eventColor: '#FFFFFF', // 全部日历日程背景色
        eventDisplay: 'block',
        allDaySlot: true, // 不显示all-day
        businessHours: true, //
        handleWindowResize: true, // 是否随浏览器窗口大小变化而自动变化。
        allDayText: '全天', // 设置all-Day显示的文字，不设置的话默认显示"all-Day"
        //themeSystem: 'bootstrap', // 主题色(本地测试未能生效)
        // loading: this.loadingEvent, // 视图数据加载中、加载完成触发（用于配合显示/隐藏加载指示器。）
        // selectAllow: this.selectAllow, //编程控制用户可以选择的地方，返回true则表示可选择，false表示不可选择
        editable: true, // 是否可以进行（拖动、缩放）修改
        eventStartEditable: true, // Event日程开始时间可以改变，默认true，如果是false其实就是指日程块不能随意拖动，只能上下拉伸改变他的endTime
        eventDurationEditable: true, // Event日程的开始结束时间距离是否可以改变，默认true，如果是false则表示开始结束时间范围不能拉伸，只能拖拽
        selectable: true, // 是否可以选中日历格
        selectMirror: true,
        selectMinDistance: 0, // 选中日历格的最小距离
        // eventLimit: true, //数据条数太多时，限制各自里显示的数据条数（多余的以“+2more”格式显示），默认false不限制,支持输入数字设定固定的显示条数
        moreLinkContent: '+ 更多', //当一块区域内容太多以"+2 more"格式显示时，这个more的名称自定义
        // dayPopoverFormat: "YYYY-M-d",
        dayMaxEventRows: true, // 日历显示事件最大条数，for all non-TimeGrid views
        weekends: false, //
        navLinks: true, // 天链接
        slotEventOverlap: false, // 相同时间段的多个日程视觉上是否允许重叠，默认true允许
        aspectRatio: 1.5, //设置日历单元格宽度与高度的比例。
        expandRows: true,
        height: 'auto',
        contentHeight: 100,
        nowIndicator: true, //周/日视图中显示今天当前时间点（以红线标记），默认false不显示
        weekNumbers: true, //是否在日历中显示周次(一年中的第几周)，如果设置为true，则会在月视图的左侧、周视图和日视图的左上角显示周数。
        weekText: '周',
        headerToolbar: false, // Fullcalendar表头显示区域不显示，显示自己自定义的html头部
        // 使用内置按钮的显示文本
        buttonText: {
          today: '今天',
          month: '月',
          week: '周',
          day: '日',
          list: '日程',
        },
        // 设置日历显示事件时间头
        slotLabelFormat: {
          hour: '2-digit',
          minute: '2-digit',
          meridiem: false,
          hour12: false, // 设置时间为24小时
        },
        // 视图的一些基本设置
        views: {
          // 月视图阳历转农历
          dayGridMonth: {
            height: 500,
            displayEventTime: true, //是否显示时间
            dayMaxEventRows: 4, // adjust to 6 only for timeGridWeek/timeGridDay
            // titleFormat: { year: "numeric", month: "2-digit", day: "2-digit" }, //控制日历显示的标题
            // moreLinkContent: "+ 更多", //可放在这里单独对每个视图控制显示更多的文字
            moreLinkClick: 'popover',
            eventTimeFormat: {
              hour: 'numeric',
              minute: '2-digit',
              meridiem: false,
            },
            dayPopoverFormat: {
              month: 'long',
              day: 'numeric',
              year: 'numeric',
            },
            //显示农历
            dayCellContent(item) {
              const _date = moment(item.date).format('YYYY-MM-DD');
              const [year, month, day] = _date.split('-');
              const lunarObj = calendar.solar2lunar(year, month, day);
              const lunarCellTxt =
                lunarObj.lunarFestival || lunarObj.festival || lunarObj.Term || `${lunarObj.IDayCn === '初一' ? lunarObj.IMonthCn : lunarObj.IDayCn}`;
              const html = `
                <div>
                  <span>${moment(item.date).format('DD')}</span>
                  <span>${lunarCellTxt}</span>
                </div>
              `;
              return { html: `<p>${html}</p>` };
            },
          },
          timeGridWeek: {},
          timeGridDay: {},
          listMonth: {},
        },
        // 设置过往时间无法点击
        // selectAllow: function (clickInfo) {
        //   if (clickInfo.end < new Date()) {
        //     return false;
        //   }
        //   return true;
        // },
        weekends: true, //是否显示周末，设为false则不显示周六和周日
        selectable: true, //是否可以选中日历格
        editable: false, //是否可以进行（拖动、缩放）修改
        navLinks: true, //天链接
        select: selectDate, //选中日历格事件
        eventClick: handleEditClick, //选中备忘录事件
        eventsSet: handleEvents,
        events: getCalendarEvents, //获取数据源
        //eventMouseEnter: eventMouseEnter, //鼠标悬浮事件
        // slotEventOverlap: true, //相同时间段的多个日程视觉上是否允许重叠，默认true允许
        // eventResize: onEventResize, // 事件时间区间调整
        // eventDrop: onEventResize, // 事件Drag-Drop事件
        // eventMouseLeave: eventMouseLeave, // 鼠标移出事件发生的事件
      });

      onMounted(() => {
        let calendarApi = fullCalendar.value.getApi();
        calendar_view_title.value = calendarApi.view.title;
        // calendar_view_week.value = calendar.view.week;
      });

      // //事件渲染
      // function handleEventDidMount(event, element, view) {
      //   console.log('wang-eventRender-1', event);
      //   if (view.name == 'listMonth') {
      //     console.log('wang-eventRender', event);
      //     element.find('.fc-list-item-title').html('wangjie');
      //   }
      // }

      // 月视图
      function handleMonth() {
        buttonGroup.value = 'month';
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.changeView('dayGridMonth');
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }
      // 周视图
      function handleWeek() {
        buttonGroup.value = 'week';
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.changeView('timeGridWeek');
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }
      // 日视图
      function handleDay() {
        buttonGroup.value = 'day';
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.changeView('timeGridDay');
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }
      // 列表视图
      function handleList() {
        buttonGroup.value = 'list';
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.changeView('listMonth');
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }
      // 鼠标划过，使用tippy插件显示tooltip
      function eventMouseEnter(info) {
        // 非周列表的情况下显示悬浮提示;
        // if (info.view.type != 'listWeek') {
        //   tippy(info.el, {
        //     content: info.event.title,
        //     placement: 'top-start',
        //   });
        // }
      }
      // 鼠标离开
      function eventMouseLeave(arg) {
        // console.log("mouseleave");
        // arg.jsEvent.preventDefault();
      }
      // 事项调整时间区间事件
      function onEventResize(arg) {
        let newTimeStart = dateFormat('YYYY-mm-dd HH:MM:SS', arg.event.startStr);
        let newTimeEnd = dateFormat('YYYY-mm-dd HH:MM:SS', arg.event.endStr);
        this.get('/calendar/updateTime', {
          id: arg.event.id,
          Start: newTimeStart,
          End: newTimeEnd,
        }).then((res) => {
          $message.success(res.data.info);
        });
        // 必须加这句，不然切换视图会有显示事件数目的bug
        let calendarApi = arg.view.calendar;
        calendarApi.today();
      }
      // 自定义按钮
      function customButton() {
        console.log('点击了自定义按钮');
      }
      // 今天
      function handleToday() {
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.today();
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        search_input.value = '';
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }
      // 上一年
      function handlePrevYear() {
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.prevYear();
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }
      // 下一年
      function handleNextYear() {
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.nextYear();
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }
      // 上一月
      function handlePrev() {
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.prev();
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }
      // 下一月
      function handleNext() {
        let calendarApi = fullCalendar.value.getApi();
        calendarApi.next();
        handleTime(calendarApi.currentData.dateProfile.activeRange);
        setTitleLabel(calendarApi.currentData.dateProfile.activeRange.start);
      }

      // 设置日期
      function setTitleLabel(dateStrat) {
        let calendarApi = fullCalendar.value.getApi();
        calendar_view_title.value = calendarApi.view.title;
        if (calendarApi.view.type == 'timeGridWeek') {
          const _date = moment(dateStrat).format('YYYY-MM-DD');
          const [year, month, day] = _date.split('-');
          calendar_view_sub_title.value = '第' + getWeek(year, month, day) + '周';
        } else if (calendarApi.view.type == 'timeGridDay') {
          var a = ['日', '一', '二', '三', '四', '五', '六'];
          var week = new Date(dateStrat).getDay();
          calendar_view_sub_title.value = '星期' + a[week];
        } else {
          calendar_view_sub_title.value = '';
        }
      }

      // 处理时间格式
      async function handleTime(activeRange) {
        await getCalendarEvents(activeRange, null, null);
      }

      //拿数据
      async function getCalendarEvents(info, successCallback, failureCallback) {
        if (route.query.time) {
          defaultDateTime = route.query.time;
          console.log(defaultDateTime);
        }
        const startTime = moment(info.start).startOf('month').unix();
        const endTime = moment(info.end).endOf('month').unix();
        const params = getQueryParams({
          startTime: startTime,
          endTime: endTime,
        });
        const events = await getCalendarList(params);
        if (successCallback) {
          successCallback(events);
        } else {
          fullCalendar.value.getApi().setOption('events', events);
        }
      }

      function getQueryParams(p) {
        const search_text = p?.search_text ?? search_input.value;
        const startTime = p?.startTime;
        const endTime = p?.endTime;
        const checkedDailyRecords = p?.checkedDailyRecords ?? planState.checkedDailyRecords;
        const checkedWorkThisWeek = p?.checkedWorkThisWeek ?? planState.checkedWorkThisWeek;
        const checkedNextWeeksPlan = p?.checkedNextWeeksPlan ?? planState.checkedNextWeeksPlan;
        const checkedParticipating = p?.checkedParticipating ?? planState.checkedParticipating;
        const selectedParticipating = p?.selectedParticipating ?? planState.selectedParticipating;
        const params = {
          startTime: startTime,
          endTime: endTime,
          searchKey: search_text,
          checkedDailyRecords: checkedDailyRecords,
          checkedWorkThisWeek: checkedWorkThisWeek,
          checkedNextWeeksPlan: checkedNextWeeksPlan,
          checkedParticipating: checkedParticipating,
          selectedParticipating: selectedParticipating,
        };
        return params;
      }

      // 获取列表信息
      async function getCalendarList(params) {
        // 以当前时间插入数据
        // 注意，请求的数据是数据库所有数据即可，不用考虑当前显示的时间范围，Fullcalendar会自动只显示当前日期范围的事件
        const data = await getTaskList(params);
        let calendarEvents = [];
        data.map((item) => {
          // 1 事件行背景着色：状态为 全天,
          // 2 事件行背景着色、事件时间展示： 非全天,跨天
          // 3 事件圆点、事件时间展示：非全天，当天
          let eventShowType = 1;
          if (item.allDay == true) {
            eventShowType = 1;
          } else if (item.allDay != true && !checkSameDay(item.beginDate, item.endDate)) {
            eventShowType = 2;
          } else if (item.allDay != true && checkSameDay(item.beginDate, item.endDate)) {
            eventShowType = 3;
          }
          let obj = {
            id: item.id,
            title: item.title,
            start: Date.parse(new Date(item.beginDate)),
            end: Date.parse(new Date(item.endDate)),
            allDay: item.allDay,
            //事件左边框颜色
            //className: item.isDone == 1 ? 'borderGreen' : 'borderOrange',
            // 非标准字段:除上述字段外，您还可以在每个事件对象中包含自己的非标准字段。FullCalendar不会修改或删除这些字段。例如，开发人员通常包括描述在回调中使用的字段，如事件呈现挂钩. 任何非标准属性都将移动到extendedProps哈希期间事件解析.
            extendedProps: {
              remark: item.remark,
              status: item.status,
              //timeText: dateFormat('HH:MM', item.beginDate),
              dotColor: '#FFF', //item.planColor,
              eventShowType: eventShowType,
              imgs:
                !item.imgs || item.imgs.length == 0
                  ? []
                  : item.imgs.split(',').map((imgurl) => {
                      return { src: imgurl, preview: true, width: 100 };
                    }),
              files:
                !item.files || item.files.length == 0
                  ? []
                  : item.files.split(',').map((fileurl) => {
                      let index = fileurl.lastIndexOf('/');
                      let fileName = fileurl.substring(index + 1);
                      return { name: fileName, url: fileurl };
                    }),
              type: item.type,
              responsible: item.createBy == userId,
            },
            others: '该字段值会被自动归类到extendedProps里面',
            backgroundColor: item.planColor, //eventShowType == 1 || eventShowType == 2 ? item.planColor : '#fff',
            textColor: '#FFF', //'#000',
            color: item.planColor, //eventShowType == 1 || eventShowType == 2 ? item.planColor : '#fff',
            editable: true, // 是否可以进行（拖动、缩放）修改
          };
          calendarEvents.push(obj);
        });
        return calendarEvents;
      }

      // 刷新数据
      async function reload() {
        let calendarApi = fullCalendar.value.getApi();
        handleTime(calendarApi.currentData.dateProfile.activeRange);
      }

      // 选择日期，填写事件
      function selectDate(arg) {
        let startTime = dateFormat('YYYY-mm-dd HH:MM', arg.startStr);
        let endTime = dateFormat('YYYY-mm-dd HH:MM', arg.startStr);
        openModal(true, {
          isUpdate: false,
          fieldTime: [startTime, endTime],
        });
        let calendarApi = arg.view.calendar;
        calendarApi.unselect(); // 清除当前日期选择
      }

      // 新增日程
      function handleCreateClick(arg) {
        let startTime = moment(new Date()).format('YYYY-MM-DD');
        let endTime = moment(new Date()).format('YYYY-MM-DD');
        openModal(true, {
          isUpdate: false,
          fieldTime: [startTime, endTime],
          id: '',
        });
      }

      // 编辑日程
      function handleEditClick(arg) {
        openModal(true, {
          isUpdate: true,
          id: arg.event.id,
        });
        let calendarApi = arg.view.calendar;
        calendarApi.unselect(); // 清除当前日期选择
      }

      // 事项标记已完成或改为未完成的事件
      async function handleCheckedClick(arg) {
        await checkedTask({ id: arg.event.id, content: arg.event.title }, reload);
      }

      // 事项删除事件
      async function handleRemoveClick(arg) {
        await deleteTask({ id: arg.event.id, content: arg.event.title }, reload);
      }

      // 当前事件绑定，此段代码可删掉
      function handleEvents(events) {}

      // 下载文件
      function fileDownload(file) {
        // console.log(this.urlToLink(file));
        // 判断是否为网页
        let bool = this.urlToLink(file);
        if (bool) {
          var b = document.createElement('a');
          b.setAttribute('href', file);
          b.setAttribute('target', '_blank');
          document.body.appendChild(b);
          b.click();
        } else {
          if (file != null || file != '') {
            this.get('/get_file_download', file, 'blob').then((res) => {
              var blob = new Blob([res.data], {
                type: 'application/octet-stream;chartset=UTF-8',
              });
              var url = window.URL.createObjectURL(blob);
              var a = document.createElement('a');
              a.href = url;
              //文件名
              let name = res.config.params.replace('F:\\flask\\upload\\', '');
              a.download = name;
              a.click();
              window.URL.revokeObjectURL(url); // 释放掉blob对象
            });
          } else {
          }
        }
      }
      // 移除对话框预览图片
      function handleRemove(file) {
        let address = this.form.img.split(',');
        address = address.filter((item) => {
          return item != file.name;
        });
        address = address.join(',');
        this.form.img = address;
        const newArray = this.filelist.filter((item, index) => {
          return item.uid != file.uid;
        });
        filelist.value = newArray;
      }

      // 判断字符串是否为网页
      function urlToLink(str) {
        var reg = /(http:\/\/|https:\/\/)((\w|=|\?|\.|\/|&|-)+)/g;
        if (reg.test(str)) {
          return true;
        } else {
          return false;
        }
      }

      // 请求数据
      async function queryCalendarList() {
        let calendarApi = fullCalendar.value.getApi();
        const info = calendarApi.currentData.dateProfile.activeRange;
        const startTime = moment(info.start).unix();
        const endTime = moment(info.end).unix();
        const params = getQueryParams({
          startTime: startTime,
          endTime: endTime,
        });
        const events = await getCalendarList(params);
        fullCalendar.value.getApi().setOption('events', events);
        title.value = '查询结果';
      }

      function handleCheckedChange() {
        queryCalendarList();
      }

      function handleSelectedChange() {
        queryCalendarList();
      }

      // 查询功能
      async function handleSearch() {
        queryCalendarList();
        // let search_text = search_input.value;
        // if (search_text != '') {
        //   queryCalendarList();
        // } else {
        //   today();
        // }
      }

      // 检测两个日期是否同一天
      function checkSameDay(startStr, endStr) {
        var startTime = dateFormat('YYYY-mm-dd', startStr);
        var endTime = dateFormat('YYYY-mm-dd', endStr);
        if (startTime == endTime) {
          return true;
        }
        return false;
      }

      // 格式化时间 fmt是所需格式化的格式，如"YYYY-mm-dd HH:MM:SS",date是所需格式化的日期
      function dateFormat(fmt, date) {
        let ret = '';
        date = new Date(date);
        const opt = {
          'Y+': date.getFullYear().toString(), // 年
          'm+': (date.getMonth() + 1).toString(), // 月
          'd+': date.getDate().toString(), // 日
          'H+': date.getHours().toString(), // 时
          'M+': date.getMinutes().toString(), // 分
          'S+': date.getSeconds().toString(), // 秒
        };
        for (let k in opt) {
          ret = new RegExp('(' + k + ')').exec(fmt);
          if (ret) {
            fmt = fmt.replace(ret[1], ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0'));
          }
        }
        return fmt;
      }

      //日期格式转换
      function formatTimer(value) {
        let date = new Date(value);
        let y = date.getFullYear();
        let MM = date.getMonth() + 1;
        MM = MM < 10 ? '0' + MM : MM;
        let d = date.getDate();
        d = d < 10 ? '0' + d : d;
        let h = date.getHours();
        h = h < 10 ? '0' + h : h;
        let m = date.getMinutes();
        m = m < 10 ? '0' + m : m;
        let s = date.getSeconds();
        s = s < 10 ? '0' + s : s;
        return h + ':' + m;
      }

      // 获取当前时间戳
      function getCurrentTime() {
        let date = new Date();
        let year = date.getFullYear();
        let month = date.getMonth() + 1;
        let day = date.getDate();
        let hour = date.getHours();
        let minute = date.getMinutes();
        let second = date.getSeconds();
        month = month < 10 ? '0' + month : month; // 可注释掉
        day = day < 10 ? '0' + day : day;
        hour = hour < 10 ? '0' + hour : hour; // 可注释掉
        minute = minute < 10 ? '0' + minute : minute;
        second = second < 10 ? '0' + second : second;
        return `${year}/${month}/${day} ${hour}:${minute}:${second}`;
      }

      function getWeek(year, month, day) {
        //计算当年一月第一天是周几
        let yearFirstDay = Number(new Date(year + '-' + 1 + '-' + 1).getDay());
        //计算某天是第几周
        let dateDay = year + '-' + month + '-' + day;
        let d1 = new Date(dateDay);
        let d2 = new Date(dateDay);
        d2.setMonth(0); //设置月份
        d2.setDate(0); //设置一月中的第一天
        let days = Math.ceil((d1 - d2) / (24 * 60 * 60 * 1000));
        let num = Math.ceil((days + yearFirstDay) / 7);
        return num;
      }

      return {
        prefixCls,
        registerModal,
        fullCalendar,
        calendarOptions,
        search_input,
        calendar_view_title,
        calendar_view_sub_title,
        dialogImageUrl,
        img_dialogVisible,
        planOptions,
        planParticipatingOptions,
        planState,
        buttonGroup,
        handleToday,
        handleMonth,
        handleWeek,
        handleDay,
        handleList,
        handleCheckedChange,
        handleSelectedChange,
        eventMouseEnter,
        eventMouseLeave,
        onEventResize,
        customButton,
        handlePrevYear,
        handleNextYear,
        handlePrev,
        handleNext,
        handleTime,
        getCalendarList,
        selectDate,
        handleCreateClick,
        handleEditClick,
        handleCheckedClick,
        handleRemoveClick,
        handleEvents,
        fileDownload,
        handleRemove,
        urlToLink,
        handleSearch,
        formatTimer,
        reload,
      };
    },
  });
</script>

<style lang="less">
  .left-calendar {
    width: 15%;
    float: left;
    height: 100%;
    background-color: #fff;
    border-bottom: 1px solid #e0e0e0;
    border-right: 1px solid #e0e0e0;
    box-shadow: 0 1px 2px #0000003d;
    padding: 10px;
  }

  .calendar-search {
    border-bottom: 1px solid rgba(0, 0, 0, 0.32) !important;
    box-sizing: border-box;
    height: 38px;
    margin: 6px auto;
    border-radius: 5px;
  }

  .icon-search {
    display: inline-block;
    font-size: 20px;
    color: #0000008a;
    position: absolute;
    z-index: 999;
    margin: 12px 9px 9px;
  }

  .calendar-search-box {
    border: none !important;
    height: 25px;
    line-height: 25px;
    margin-top: 7px;
    padding: 0 5px 0 40px;
    width: 100%;
    box-shadow: none !important;
  }

  .calendar-type {
    overflow-x: hidden;
    overflow-y: auto;
  }

  .calendar-type-title {
    width: 100%;
  }

  .font-color {
    color: #0000008a;
    font-size: 13px;
  }

  .calendar-type-List {
    width: 100%;
  }

  .calendar-type-List > ul {
    font-size: 13px;
    padding: 10px 10px 0;
    width: 100%;
    border-color: #00000026;
  }

  .calendar-type-List li {
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    cursor: move;
    font-size: 12px;
    overflow: hidden;
    height: 40px;
    line-height: 40px;
    position: relative;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 100%;
  }

  .task-select .ant-select-selector {
    border: none !important;
    box-shadow: none !important;
  }

  .right-left-header {
    background: hsla(0, 0%, 100%, 0.9);
    box-shadow: 0 1px 2px #00000029;
    height: 45px;
    padding: 0 28px;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
    width: 100%;
    float: left;
    z-index: 8;
  }

  .right-left-header h2 {
    display: inline-block;
    font-size: 16px;
    font-weight: 400;
    margin-left: 20px;
    line-height: 45px;
  }

  .right-center-header {
    position: absolute;
    left: 50%;
    font-size: 1em;
    width: 220px;
    float: left;
  }

  .right-right-header {
    float: right;
    height: 32px;
    line-height: 32px;
    margin-top: 7px;
    position: absolute;
    right: 20px;
  }

  .right-right-header .right-button {
    border-radius: 18px;
    color: #fff;
    background-color: #1e88e5;
  }

  .today {
    float: left;
    color: #333;
    height: 30px;
    line-height: 30px;
    margin-top: 8px;
    padding: 0;
    text-align: center;
    width: 46px;
    border-radius: 4px;
    border: 1px solid #ddd;
  }

  .prev-next {
    float: left;
    color: #333;
    height: 30px;
    line-height: 30px;
    margin-top: 8px;
    padding: 0;
    text-align: center;
    width: 30px;
    border-radius: 4px;
    border: 1px solid #ddd;
  }

  .fc-button-group {
    height: 45px;
    line-height: 45px;
    box-shadow: none;
    display: inline-block;
    box-sizing: border-box;
  }

  .border-color {
    border-color: #1e88e5 !important;
  }

  .fc-button-group .border-color {
    border-color: #1e88e5;
    color: #1e88e5;
  }

  .fc-button-group .common-button {
    border: 0;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    box-shadow: none;
    box-sizing: border-box;
    height: 45px;
    line-height: 48px;
    margin: 0 10px;
    padding: 0;
    transition: border-color 0.3s ease-in-out;
    width: 34px;
  }

  .plan-calendar {
    margin: 12px;
    background-color: @component-background;
    padding: 8px 10px 8px 10px;
    .plan-calendar-content {
      background-color: white;
    }
    a {
      color: #080808 !important;
    }
  }

  .tippy-box[data-theme~='tomato'] {
    //自定义主题，这里的tomato是自定义主题的名称
    background-color: tomato; //自定义主题的背景色
    color: yellow; //自定义主题的字体颜色
  }

  .tippy-box[data-theme~='tomato'][data-placement^='top'] > .tippy-arrow::before {
    //修改箭头的颜色
    border-top-color: tomato;
  }

  .calendar_matters .a-dialog__body {
    height: 450px;
    overflow: auto;
  }
  .calendar_details .a-textarea__inner {
    font-weight: bold;
    font-family: Arial, Helvetica, sans-serif;
    color: #000;
    height: 120px;
  }
  .calendar_matters .a-dialog__header {
    border-radius: 5px;
    background-color: #cae1f7;
    align-content: center;
    padding: 15px;
    font-weight: bold;
    border-bottom-style: solid;
    border-bottom-width: 1px;
    border-bottom-color: aliceblue;
  }
  .fc-daygrid-day-top p {
    font-size: 13px;
    color: #606266;
    margin-right: 10px;
  }
  .fc .fc-toolbar.fc-header-toolbar {
    margin-bottom: 10px;
  }
  .userName .a-input__inner {
    font-weight: bold;
    color: #000000ab;
  }
  .attachment .a-form-item__content {
    display: flex;
  }
  .upload-demo .a-upload-list--picture-card .a-upload-list__item {
    height: 120px;
    width: 120px;
  }
  .upload-demo .a-upload--picture-card {
    height: 120px;
    width: 120px;
    line-height: 120px;
  }
  .dateRange .a-range-input {
    font-weight: bold;
    color: #080808;
  }
  .calendar .fc-header-toolbar {
    margin-bottom: 5px;
  }
  .calendar .borderGreen {
    border-left: 5px solid #44bb08 !important;
    border-radius: 0;
    border: none;
    white-space: normal;
    overflow: hidden;
    text-overflow: ellipsis;
    span {
      color: #000;
      font-weight: bold;
    }
  }
  .calendar .borderOrange {
    border-left: 5px solid #fe9b02 !important;
    border-radius: 0;
    border: none;
    white-space: normal;
    overflow: hidden;
    span {
      color: #000;
      font-weight: bold;
    }
  }
  .calendar .borderOrigin {
    border-radius: 0;
    border: none;
    white-space: normal;
    overflow: hidden;
    text-overflow: ellipsis;
    max-height: 150px;
    span {
      color: #000;
      font-weight: bold;
    }
  }
  .calendar .fc-event-title {
    font-weight: bold;
    color: #000;
    overflow: hidden;
  }
  .calendar .fc-event-time {
    font-weight: bold;
    color: #000;
  }
  .calendar .fc-daygrid-event-dot {
    border: none;
  }
  .popover {
    .a-popover {
      max-height: 350px;
    }
  }
  .popover_title {
    font-weight: bold;
    margin-bottom: 3px;
  }
  .popover_content {
    color: #000;
    font-size: 13px;
  }
  .popoverShowImg {
    width: auto;
    cursor: pointer;
    .a-image__inner {
      max-height: 200px;
    }
  }
  .link {
    color: #000;
    font-size: 12px;
    font-weight: bold;
    margin-top: 2px;
    & :hove {
      color: #66b1ff;
    }
  }
  .fc_btns {
    padding: 10px 12px;
  }
  .a-icon-search {
    line-height: 2.5;
    margin-right: 8px;
  }
  .fc-right {
    display: flex;
    flex: 1.5;
    justify-content: flex-end;
  }
  .tip-content {
    line-height: 2.2;
    margin-right: 4px;
    font-weight: 600;
  }
  .title {
    margin: 0px 5px;
    line-height: 1.8;
    font-size: 16px;
  }
  .event-dot {
    margin: 0 4px;
    box-sizing: content-box;
    width: 0;
    height: 0;
    border: 4px solid #3788d8;
    border-radius: 4px;
  }
  .calendar_matters {
    width: 100%;
  }
  .calendar .a-popover__reference {
    display: grid;
    max-height: 150px;
    overflow: auto;
  }
  .a-popover__reference::-webkit-scrollbar {
    /*滚动条整体样式*/
    width: 8px; /*高宽分别对应横竖滚动条的尺寸*/
    height: 1px;
  }
  .a-popover__reference::-webkit-scrollbar-thumb {
    /*滚动条里面小方块*/
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    background: #535353;
  }
  .a-popover__reference::-webkit-scrollbar-track {
    /*滚动条里面轨道*/
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    border-radius: 2px;
    background: #ededed;
  }
  .popover .a-popover__title {
    font-weight: bold;
    margin-bottom: 5px;
    border-bottom: solid 1px;
    padding: 2px;
  }
  @media only screen and (max-width: 767px) {
    .fc-toolbar {
      flex-direction: column;
    }
    .fc-left {
      flex: 1 !important;
    }
    .tips {
      flex: 1 !important;
      justify-content: center;
      margin-bottom: 5px;
    }
    .fc-center {
      flex: 1 !important;
      margin: 5px 0px;
    }
    .fc-right {
      flex: 1;
      justify-content: center !important;
      margin-bottom: 5px;
    }
    .tip-content {
      line-height: 1 !important;
      margin-right: 4px;
      font-weight: 600;
    }
    .title {
      font-size: 20px;
      font-weight: 700;
      line-height: 1.9 !important;
    }
    .fc-list-table {
      word-break: break-all;
      overflow: auto;
    }
    .fc-list-event-title {
      overflow: auto;
    }
    .a-dialog {
      width: 90%;
    }
    .dateRange {
      overflow: auto;
    }
  }
</style>
